﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace MacomberMapSystem.Common.Exports
{
    /// <summary>
    /// This class holds information on an exported point, so that the shifting can occur left-right, etc.    
    /// </summary>
    public class MM_DDL_ExportPoint
    {
        #region Variable declarations
        /// <summary>The original location of the element</summary>
        public Point Origin;

        /// <summary>The name of the object (picture, symbol, etc.)</summary>
        public string Name;

        /// <summary>The type of point being contained </summary>
        public enum enumPointType
        {
            /// <summary>A picture with data bindings</summary>
            DataBoundPicture,
            /// <summary>A symbol with no data bindings</summary>
            Symbol,
            /// <summary>Static text with a GAB</summary>
            Text
        }

        /// <summary>The point type</summary>
        public enumPointType PointType;

        /// <summary>The data-linkage keys, if any</summary>
        public string[] Keys;
        #endregion

        #region Initialization        



        /// <summary>
        /// Initialize a new data-bound picture
        /// </summary>
        /// <param name="Picture"></param>
        /// <param name="Origin"></param>
        /// <param name="Keys"></param>
        /// <returns></returns>
        public static MM_DDL_ExportPoint DataBoundPicture(string Picture, Point Origin, params string[] Keys)
        {
            MM_DDL_ExportPoint OutPoint = new MM_DDL_ExportPoint();
            OutPoint.Name = Picture;
            OutPoint.Origin = Origin;
            OutPoint.Keys = Keys;
            OutPoint.PointType = enumPointType.DataBoundPicture;
            return OutPoint;
        }

        /// <summary>
        /// Initialize a new symbol
        /// </summary>
        /// <param name="InSymbol"></param>
        /// <param name="Origin"></param>
        /// <returns></returns>
        public static MM_DDL_ExportPoint Symbol(String InSymbol, Point Origin)
        {
            MM_DDL_ExportPoint OutPoint = new MM_DDL_ExportPoint();
            OutPoint.Name = InSymbol;
            OutPoint.Origin = Origin;            
            OutPoint.PointType = enumPointType.Symbol;
            return OutPoint;
        }

        /// <summary>
        /// Initialize a new text point
        /// </summary>
        /// <param name="Gab"></param>
        /// <param name="InText"></param>
        /// <param name="Origin"></param>
        /// <returns></returns>
        public static MM_DDL_ExportPoint Text(String Gab, String InText, Point Origin)
        {
            MM_DDL_ExportPoint OutPoint = new MM_DDL_ExportPoint();
            OutPoint.Name = Gab;
            OutPoint.Origin = Origin;
            OutPoint.Keys = new string[] { InText };
            OutPoint.PointType = enumPointType.Text;
            return OutPoint;
        }

        private MM_DDL_ExportPoint()
        { }
        #endregion


        /// <summary>
        /// Shift our points, such that the labels are more viewable
        /// </summary>
        /// <param name="ExportPoints"></param>
        /// <param name="LabelBounds"></param>
        /// <param name="ElemBounds"></param>
        /// <param name="OutStream"></param>
        public static void ShiftPoints(List<MM_DDL_ExportPoint> ExportPoints, Rectangle LabelBounds, Rectangle ElemBounds, MM_DDL_Exporter_Stream OutStream)                       
        {
            
            //Build our list of each exported coordinate, and our guess at its bounds
            Dictionary<MM_DDL_ExportPoint, Rectangle> ToExport = new Dictionary<MM_DDL_ExportPoint, Rectangle>();
            int MaxTop = 0, MaxLeft = 0;
            int Left = Int32.MaxValue, Top = Int32.MaxValue, Right = 0, Bottom = 0;
            foreach (MM_DDL_ExportPoint Pt in ExportPoints)
            {
                Rectangle OutRect;
                if (Pt.Name == "TEXT_FV_CHR_NONENTRY_SIMPLE_ERCOT")
                    using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
                    using (Font f = new Font("Arial", 12))
                    {
                        Size MaxSize = Size.Ceiling(g.MeasureString(Pt.Keys[0], f));
                        OutRect = new Rectangle(Pt.Origin, MaxSize);
                    }
                else if (Pt.Name.Contains("_LABEL"))
                    using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
                    using (Font f = new Font("Arial", 12))
                    {
                        Size MaxSize = Size.Ceiling(g.MeasureString(Pt.Keys[Pt.Keys.Length - 1].Split('=')[1], f));
                        OutRect = new Rectangle(Pt.Origin, MaxSize);
                    }
                else if (Pt.Name == "KV_NETWORK")
                    OutRect = new Rectangle(Pt.Origin, new Size(58, 18));
                else if (Pt.Name == "ANALOG_SUBSTN_NET" || Pt.Name == "DEVICE_SUBSTN")
                    OutRect = new Rectangle(Pt.Origin, new Size(113, 16));
                else if (Pt.Name.StartsWith("ANALOG_N_"))
                    OutRect = new Rectangle(Pt.Origin, new Size(88, 31));
                else if (Pt.Name == "KV_BUS")
                    OutRect = new Rectangle(Pt.Origin, new Size(101, 19));
                else if (Pt.Name=="ANALOG_U"||Pt.Name=="ANALOG_D"||Pt.Name=="ANALOG_R"||Pt.Name=="ANALOG_L")
                    OutRect = new Rectangle(Pt.Origin, new Size(120, 20));
                else if (Pt.Name == "ANALOG_10PNT_U" || Pt.Name == "ANALOG_10PNT_D" || Pt.Name == "ANALOG_10PNT_R" || Pt.Name == "ANALOG_10PNT_L" || Pt.Name == "ANALOG_10PNT_TAP")
                    OutRect = new Rectangle(Pt.Origin, new Size(88,13));                
                else
                    throw new InvalidOperationException("Unknown element type: " + Pt.Name);
                
                ToExport.Add(Pt, OutRect);
                Left = Math.Min(OutRect.Left, Left);
                Top = Math.Min(OutRect.Top, Top);
                Right = Math.Max(OutRect.Right, Right);
                Bottom = Math.Max(OutRect.Bottom, Bottom);
                MaxLeft = Math.Max(OutRect.Left, Left);
                MaxTop = Math.Max(OutRect.Top, Top);
                
            }

            bool LabelAbove = LabelBounds.Bottom <= ElemBounds.Top;
            bool LabelBelow = LabelBounds.Top >= ElemBounds.Bottom;
            bool LabelLeft = LabelBounds.Right <= ElemBounds.Left;
            bool LabelRight = LabelBounds.Left >= ElemBounds.Right;
            Rectangle TargetRect = Rectangle.FromLTRB(Left, Top, Right, Bottom);

            //Draw our rectangle to show us what we were thinking
            

            Point Offset = Point.Empty;
            if (LabelAbove)                
                Offset = new Point((LabelBounds.Width - TargetRect.Width)/2, MaxTop - Bottom);
            else if (LabelBelow)
                Offset = new Point((LabelBounds.Width - TargetRect.Width) / 2, 0);
            else if (LabelLeft)
                Offset.X -= TargetRect.Width - LabelBounds.Width;
            
            //if (ToExport.Count > 0)
             //   OutStream.WriteRectangle(TargetRect, Offset, "SWITCH_CLOSE_230KV");

           
            foreach (KeyValuePair<MM_DDL_ExportPoint, Rectangle> kvp in ToExport)                      
                if (kvp.Key.PointType == enumPointType.DataBoundPicture && kvp.Key.Name.StartsWith("TRANS"))
                    OutStream.WriteDataBoundPicture(kvp.Key.Name, new Point(kvp.Key.Origin.X + Offset.X + ((TargetRect.Width - kvp.Value.Width) / 2), kvp.Key.Origin.Y + Offset.Y), kvp.Key.Keys);
                else if (kvp.Key.PointType == enumPointType.DataBoundPicture )
                    OutStream.WriteDataBoundPicture(kvp.Key.Name, new Point(kvp.Key.Origin.X + Offset.X, kvp.Key.Origin.Y + Offset.Y), kvp.Key.Keys);
                else if (kvp.Key.PointType == enumPointType.Symbol)
                    OutStream.WriteSymbol(kvp.Key.Name, new Point(kvp.Key.Origin.X + Offset.X + ((TargetRect.Width - kvp.Value.Width) / 2), kvp.Key.Origin.Y + Offset.Y));
                else if (kvp.Key.PointType == enumPointType.Text)
                    OutStream.WriteTextWithGab(kvp.Key.Keys[0], kvp.Key.Name, new Point(kvp.Key.Origin.X + Offset.X + ((TargetRect.Width - kvp.Value.Width)/2), kvp.Key.Origin.Y + Offset.Y), false, false);
               
        }
    }
}
